/*
 * Copyright (c) 2009, Jan Pastor. All Rights Reserved.
 */

package sk.jp.commons.tools;

/**
 * Utility to get current JVM memory state.
 */
public class MemoryState {

    /**
     * Constant to convert values to kB.
     */
    public static final long KBYTES = 1024;

    /**
     * Constant to convert values to MB.
     */
    public static final long MBYTES = KBYTES*1024;

    /**
     * Constant to convert values to GB.
     */
    public static final long GBYTES = MBYTES*1024;

    //----------------------------------------------------------------------

    /**
     * Free memory of allocated heap.
     */
    public final long heapFreeMemory;

    /**
     * Amount of allocated heap memory.
     */
    public final long heapMaxMemory;

    /**
     * Max limit of available memory fo JVM.
     */
    public final long totalMaxMemory;

    /**
     * Amount of used memory.
     */
    public final long totalUsedMemory;

    /**
     * Amount of used memory (% of {@link #totalMaxMemory}).
     */
    public final long totalUsedMemoryPerc;

    /**
     * Amount of free (additionaly available) memory.
     */
    public final long totalFreeMemory;

    /**
     * Amount of free (additionaly available) memory (% of {@link #totalMaxMemory}).
     */
    public final long totalFreeMemoryPerc;

    //----------------------------------------------------------------------

    private MemoryState(long heapFreeMemory, long heapMaxMemory, long totalMaxMemory,
                       long totalUsedMemory, long totalUsedMemoryPerc,
                       long totalFreeMemory, long totalFreeMemoryPerc) {
        this.heapFreeMemory = heapFreeMemory;
        this.heapMaxMemory = heapMaxMemory;
        this.totalMaxMemory = totalMaxMemory;
        this.totalUsedMemory = totalUsedMemory;
        this.totalUsedMemoryPerc = totalUsedMemoryPerc;
        this.totalFreeMemory = totalFreeMemory;
        this.totalFreeMemoryPerc = totalFreeMemoryPerc;
    }

    /**
     * Conventional method to convert value to given units.
     * @param valueBytes value to convert.
     * @param units units of bytes (see {@link #KBYTES}, {@link #MBYTES}, {@link #GBYTES}).
     * @return converted value rounded to integer.
     */
    public long convert(long valueBytes, long units){
        return valueBytes / units;
    }

    //----------------------------------------------------------------------

    /**
     * Returns current JVM memory state.
     * @return current JVM memory state.
     */
    public static MemoryState get(){
        Runtime runtime = Runtime.getRuntime();
        long heapFreeMemory = runtime.freeMemory();
        long heapMaxMemory = runtime.totalMemory();
        long totalMaxMemory = runtime.maxMemory();

        long totalUsedMemory = heapMaxMemory - heapFreeMemory;
        double usedPerc = (double) totalUsedMemory / (double) totalMaxMemory * 100.0;
        long totalUsedMemoryPerc = Math.round(usedPerc);
        long totalFreeMemory = totalMaxMemory - totalUsedMemory;
        long totalFreeMemoryPerc = 100 - totalUsedMemoryPerc;

        return new MemoryState(heapFreeMemory, heapMaxMemory, totalMaxMemory, totalUsedMemory,
                               totalUsedMemoryPerc, totalFreeMemory, totalFreeMemoryPerc);
    }

}
